package cc.minos.servers.openfire.chats
{
	import cc.minos.console.Console;
	import cc.minos.servers.openfire.events.ChatEvent;
	import cc.minos.servers.openfire.managers.OpenFireManager;
	import flash.events.Event;
	import org.igniterealtime.xiff.collections.ArrayCollection;
	import org.igniterealtime.xiff.collections.events.CollectionEvent;
	import org.igniterealtime.xiff.conference.Room;
	import org.igniterealtime.xiff.conference.RoomOccupant;
	import org.igniterealtime.xiff.core.UnescapedJID;
	import org.igniterealtime.xiff.data.Message;
	import org.igniterealtime.xiff.data.muc.MUCItem;
	import org.igniterealtime.xiff.data.muc.MUCUserExtension;
	import org.igniterealtime.xiff.events.RoomEvent;
	
	/**
	 * ...
	 * @author Minos
	 */
	public class GroupChat extends SimpleChat
	{
		
		public static const ROOM_JOIN_FAILED:String = "roomJoinFailed";
		public static const ROOM_OCCUPANTS_CHANGED:String = "roomOccupantsChanged";
		
		protected var _room:Room;
		private var roomPassword:String = null;
		private var recentlyChangedNicks:Object = null;
		private var firstOccupants:ArrayCollection;
		
		public function GroupChat( j:UnescapedJID )
		{
			super( j );
		}
		
		override public function setup( j:UnescapedJID ):void
		{
			room = OpenFireManager.mucManager.getRoom( j );
			displayName = room.roomJID.toString();
			if ( roomPassword != null )
				room.password = roomPassword;
				
			addRoomListeners();
			
			if ( !room.join() )
			{
				dispatchEvent( new Event( ROOM_JOIN_FAILED ) );
				return;
			}
			
			if ( room.role == Room.ROLE_MODERATOR )
			{
				//Debug.log("Change room config" , this );
				var roomConfig : Object = { };
				roomConfig[ "muc#roomconfig_maxusers" ] = [ 0 ];
				roomConfig[ "muc#roomconfig_persistentroom" ] = [ 0 ];
				room.configure( roomConfig );
			}
			
			room.addEventListener( CollectionEvent.COLLECTION_CHANGE , function( e:CollectionEvent ):void
				{
					dispatchEvent( new Event( ROOM_OCCUPANTS_CHANGED ) );
				} );
			
		}
		
		private function addRoomListeners():void
		{
			room.addEventListener( RoomEvent.USER_JOIN , handleUserJoin );
			room.addEventListener( RoomEvent.USER_DEPARTURE , handleUserDeparture );
			room.addEventListener( RoomEvent.USER_KICKED , handleUserKicked );
			room.addEventListener( RoomEvent.USER_BANNED , handleUserBanned );
			
			room.addEventListener( RoomEvent.PASSWORD_ERROR , handlePasswordError );
			room.addEventListener( RoomEvent.REGISTRATION_REQ_ERROR , handleRegistrationReqError );
			room.addEventListener( RoomEvent.BANNED_ERROR , handleBannedError );
			room.addEventListener( RoomEvent.NICK_CONFLICT , handleNickConflict );
			room.addEventListener( RoomEvent.MAX_USERS_ERROR , handleMaxUsersError );
			room.addEventListener( RoomEvent.LOCKED_ERROR , handleLockedError );
		}
		
		private function removeRoomListeners():void
		{
			room.removeEventListener( RoomEvent.USER_JOIN , handleUserJoin );
			room.removeEventListener( RoomEvent.USER_DEPARTURE , handleUserDeparture );
			room.removeEventListener( RoomEvent.USER_KICKED , handleUserKicked );
			room.removeEventListener( RoomEvent.USER_BANNED , handleUserBanned );
			
			room.removeEventListener( RoomEvent.PASSWORD_ERROR , handlePasswordError );
			room.removeEventListener( RoomEvent.REGISTRATION_REQ_ERROR , handleRegistrationReqError );
			room.removeEventListener( RoomEvent.BANNED_ERROR , handleBannedError );
			room.removeEventListener( RoomEvent.NICK_CONFLICT , handleNickConflict );
			room.removeEventListener( RoomEvent.MAX_USERS_ERROR , handleMaxUsersError );
			room.removeEventListener( RoomEvent.LOCKED_ERROR , handleLockedError );
		}
		
		
		
		override public function close():void
		{
			removeRoomListeners();
			super.close();
			room.leave();
		}
		
		override public function get jid():UnescapedJID
		{
			return room.roomJID;
		}
		
		override public function get myNickName():String
		{
			return room.nickname;
		}
		
		override public function insertMessage( message:ChatMessage ):void
		{
			if ( room.isThisUser( message.from ) )
				return;
			super.insertMessage( message );
		}
		
		override public function transmitMessage( message:ChatMessage ):void
		{
			OpenFireManager.messageManager.sendMessage( jid , message.body , Message.TYPE_GROUPCHAT );
			inputUI.clearText();
		}
		
		override public function set displayName( value:String ):void
		{
			if ( value.indexOf( '@' ) > -1 )
				value = value.split( '@' )[ 0 ];
			super.displayName = value;
		}
		
		override public function get occupants():ArrayCollection
		{
			return new ArrayCollection( room.toArray() );
		}
		
		public function set password( pw:String ):void
		{
			roomPassword = pw;
		}
		
		public function get room():Room
		{
			return _room;
		}
		
		public function set room( value:Room ):void
		{
			_room = value;
		}
		
		private function error( type:String , close:Boolean = true ):void
		{
			var errEvt:ChatEvent = new ChatEvent( ChatEvent.CHAT_ERROR );
			errEvt.error = type;
			errEvt.chat = this;
			Console.log( type , this , Console.ERROR );
			OpenFireManager.chatManager.closeChat( this );
			OpenFireManager.chatManager.broadcastEvent( errEvt );
			//removeErrorEventListeners();
			removeRoomListeners();
		}
		
		public function handleUserJoin( e:RoomEvent ):void
		{
			if ( recentlyChangedNicks != null )
			{
				var nickChange:Array = recentlyChangedNicks[ e.nickname ];
				if ( nickChange != null )
				{
					delete recentlyChangedNicks[ e.nickname ];
					return;
				}
			}
			
			if ( e.nickname != myNickName )
				insertSystemMessage( e.nickname + " 进入房间!" );
		}
		
		public function handleUserDeparture( e:RoomEvent ):void
		{
			var userExt:MUCUserExtension = e.data.getAllExtensionsByNS( MUCUserExtension.NS )[ 0 ];
			if ( userExt && userExt.hasStatusCode( 303 ) )
			{
				if ( recentlyChangedNicks == null )
					recentlyChangedNicks = new Object();
				//var userExtItem:MUCItem = userExt.getAllItems()[ 0 ];
				var userExtItem:MUCItem = userExt.items[0];
				recentlyChangedNicks[ userExtItem.nick ] = [ e.nickname , userExtItem.nick ];
				return;
			}
			
			insertSystemMessage( e.nickname + " 退出房间!" );
		}
		
		private function onRoomAffiliations( e:RoomEvent ):void
		{
		}
		
		private function handleUserKicked( e:RoomEvent ):void
		{
			insertSystemMessage( e.nickname + " 被踢出房间!" );
		}
		
		private function handleUserBanned( e:RoomEvent ):void
		{
			insertSystemMessage( e.nickname + " 被禁止!" );
		}
		
		private function handlePasswordError( e:RoomEvent ):void
		{
			error( ChatEvent.PASSWORD_ERROR );
		}
		
		private function handleRegistrationReqError( e:RoomEvent ):void
		{
			error( ChatEvent.REGISTRATION_REQUIRED_ERROR );
		}
		
		private function handleBannedError( e:RoomEvent ):void
		{
			error( ChatEvent.BANNED_ERROR );
		}
		
		private function handleNickConflict( e:RoomEvent ):void
		{
			if( OpenFireManager.config.duplication ){
				var reg:RegExp = /[0-9]{1,3}\b/
				var tmp:String = OpenFireManager.config.nickname;
				var no:String = reg.test( tmp ) ? tmp.match( reg )[0] : '';
				if ( no == '' ) {
					tmp += Math.round( Math.random() * 100 );
				}else {
					tmp = tmp.replace( no , Math.round( Math.random() * 10000 ) );
				}
				OpenFireManager.config.nickname = room.nickname = tmp;
				room.join();
			}else
				error( ChatEvent.NICK_CONFLICT_ERROR );
		}
		
		private function handleMaxUsersError( e:RoomEvent ):void
		{
			error( ChatEvent.MAX_USERS_ERROR );
		}
		
		private function handleLockedError( e:RoomEvent ):void
		{
			error( ChatEvent.ROOM_LOCKED_ERROR );
		}
	
	}

}